﻿using System;
using System.Collections.Generic;
using Terraria.ID;
using Terraria.ModLoader.Exceptions;

namespace Terraria.ModLoader
{
	// Token: 0x02000201 RID: 513
	public class RecipeFinder
	{
		// Token: 0x060016C3 RID: 5827 RVA: 0x004161A4 File Offset: 0x004143A4
		public void AddIngredient(int itemID, int stack = 1)
		{
			if (itemID <= 0 || itemID >= ItemLoader.ItemCount)
			{
				throw new RecipeException("No item has ID " + itemID);
			}
			Item item = new Item();
			item.SetDefaults(itemID, false);
			item.stack = stack;
			this.items.Add(item);
		}

		// Token: 0x060016C4 RID: 5828 RVA: 0x004161F4 File Offset: 0x004143F4
		public void AddRecipeGroup(string name, int stack = 1)
		{
			if (!RecipeGroup.recipeGroupIDs.ContainsKey(name))
			{
				throw new RecipeException("No recipe group is named " + name);
			}
			int num = RecipeGroup.recipeGroupIDs[name];
			RecipeGroup recipeGroup = RecipeGroup.recipeGroups[num];
			this.AddIngredient(recipeGroup.ValidItems[recipeGroup.IconicItemIndex], stack);
			this.groups.Add(num);
		}

		// Token: 0x060016C5 RID: 5829 RVA: 0x000115D8 File Offset: 0x0000F7D8
		public void SetResult(int itemID, int stack = 1)
		{
			if (itemID <= 0 || itemID >= ItemLoader.ItemCount)
			{
				throw new RecipeException("No item has ID " + itemID);
			}
			this.result.SetDefaults(itemID, false);
			this.result.stack = stack;
		}

		// Token: 0x060016C6 RID: 5830 RVA: 0x00011615 File Offset: 0x0000F815
		public void AddTile(int tileID)
		{
			if (tileID < 0 || tileID >= TileLoader.TileCount)
			{
				throw new RecipeException("No tile has ID " + tileID);
			}
			this.tiles.Add(tileID);
		}

		// Token: 0x060016C7 RID: 5831 RVA: 0x0041625C File Offset: 0x0041445C
		public Recipe FindExactRecipe()
		{
			for (int i = 0; i < Recipe.numRecipes; i++)
			{
				Recipe recipe = Main.recipe[i];
				bool flag = true;
				List<Item> list = new List<Item>(this.items);
				for (int j = 0; j < Recipe.maxRequirements; j++)
				{
					Item item = recipe.requiredItem[j];
					if (item.type == 0)
					{
						break;
					}
					bool flag2 = false;
					for (int k = 0; k < list.Count; k++)
					{
						if (item.type == list[k].type && item.stack == list[k].stack)
						{
							flag2 = true;
							list.RemoveAt(k);
							break;
						}
					}
					if (!flag2)
					{
						flag = false;
						break;
					}
				}
				if (list.Count > 0)
				{
					flag = false;
				}
				List<int> list2 = new List<int>(this.groups);
				List<int> acceptedGroups = RecipeFinder.GetAcceptedGroups(recipe);
				for (int l = 0; l < acceptedGroups.Count; l++)
				{
					int num = acceptedGroups[l];
					bool flag3 = false;
					for (int m = 0; m < list2.Count; m++)
					{
						if (num == list2[m])
						{
							flag3 = true;
							list2.RemoveAt(m);
							break;
						}
					}
					if (!flag3)
					{
						flag = false;
						break;
					}
				}
				if (list2.Count > 0)
				{
					flag = false;
				}
				if (this.result.type != recipe.createItem.type || this.result.stack != recipe.createItem.stack)
				{
					flag = false;
				}
				List<int> list3 = new List<int>(this.tiles);
				for (int n = 0; n < Recipe.maxRequirements; n++)
				{
					int num2 = recipe.requiredTile[n];
					if (num2 == -1)
					{
						break;
					}
					bool flag4 = false;
					for (int num3 = 0; num3 < list3.Count; num3++)
					{
						if (num2 == list3[num3])
						{
							flag4 = true;
							list3.RemoveAt(num3);
							break;
						}
					}
					if (!flag4)
					{
						flag = false;
						break;
					}
				}
				if (list3.Count > 0)
				{
					flag = false;
				}
				if (this.needWater != recipe.needWater)
				{
					flag = false;
				}
				else if (this.needLava != recipe.needLava)
				{
					flag = false;
				}
				else if (this.needHoney != recipe.needHoney)
				{
					flag = false;
				}
				if (flag)
				{
					return recipe;
				}
			}
			return null;
		}

		// Token: 0x060016C8 RID: 5832 RVA: 0x00416484 File Offset: 0x00414684
		public List<Recipe> SearchRecipes()
		{
			List<Recipe> list = new List<Recipe>();
			for (int i = 0; i < Recipe.numRecipes; i++)
			{
				Recipe recipe = Main.recipe[i];
				bool flag = true;
				List<Item> list2 = new List<Item>(this.items);
				for (int j = 0; j < Recipe.maxRequirements; j++)
				{
					Item item = recipe.requiredItem[j];
					if (item.type == 0)
					{
						break;
					}
					for (int k = 0; k < list2.Count; k++)
					{
						if (item.type == list2[k].type && item.stack >= list2[k].stack)
						{
							list2.RemoveAt(k);
							break;
						}
					}
				}
				if (list2.Count > 0)
				{
					flag = false;
				}
				List<int> list3 = new List<int>(this.groups);
				List<int> acceptedGroups = RecipeFinder.GetAcceptedGroups(recipe);
				for (int l = 0; l < acceptedGroups.Count; l++)
				{
					int num = acceptedGroups[l];
					for (int m = 0; m < list3.Count; m++)
					{
						if (num == list3[m])
						{
							list3.RemoveAt(m);
							break;
						}
					}
				}
				if (list3.Count > 0)
				{
					flag = false;
				}
				if (this.result.type != 0)
				{
					if (this.result.type != recipe.createItem.type)
					{
						flag = false;
					}
					else if (this.result.stack > recipe.createItem.stack)
					{
						flag = false;
					}
				}
				List<int> list4 = new List<int>(this.tiles);
				for (int n = 0; n < Recipe.maxRequirements; n++)
				{
					int num2 = recipe.requiredTile[n];
					if (num2 == -1)
					{
						break;
					}
					for (int num3 = 0; num3 < list4.Count; num3++)
					{
						if (num2 == list4[num3])
						{
							list4.RemoveAt(num3);
							break;
						}
					}
				}
				if (list4.Count > 0)
				{
					flag = false;
				}
				if (this.needWater && !recipe.needWater)
				{
					flag = false;
				}
				else if (this.needLava && !recipe.needLava)
				{
					flag = false;
				}
				else if (this.needHoney && !recipe.needHoney)
				{
					flag = false;
				}
				if (flag)
				{
					list.Add(recipe);
				}
			}
			return list;
		}

		// Token: 0x060016C9 RID: 5833 RVA: 0x004166AC File Offset: 0x004148AC
		private static List<int> GetAcceptedGroups(Recipe recipe)
		{
			List<int> list = new List<int>(recipe.acceptedGroups);
			if (recipe.anyWood)
			{
				list.Add(RecipeGroupID.Wood);
			}
			if (recipe.anyIronBar)
			{
				list.Add(RecipeGroupID.IronBar);
			}
			if (recipe.anySand)
			{
				list.Add(RecipeGroupID.Sand);
			}
			if (recipe.anyPressurePlate)
			{
				list.Add(RecipeGroupID.PressurePlate);
			}
			if (recipe.anyFragment)
			{
				list.Add(RecipeGroupID.Fragment);
			}
			return list;
		}

		// Token: 0x040015A5 RID: 5541
		private List<Item> items = new List<Item>();

		// Token: 0x040015A6 RID: 5542
		private List<int> groups = new List<int>();

		// Token: 0x040015A7 RID: 5543
		private Item result = new Item();

		// Token: 0x040015A8 RID: 5544
		private List<int> tiles = new List<int>();

		// Token: 0x040015A9 RID: 5545
		public bool needWater;

		// Token: 0x040015AA RID: 5546
		public bool needLava;

		// Token: 0x040015AB RID: 5547
		public bool needHoney;
	}
}
